<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 使用在线地址 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> -->

    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 视图(view)  页面,用于做html展示 -->
    <!-- {{msg}}  Vue的模板语法(文本插值,类似ES6的模板字符串${}, 将{{}} 内的值拼接到标签内,作为标签内的文本 )   -->
    <div id="app">
        <p>{{msg}}</p>
        <p>{{count}}</p>
        <p>{{info.name}}---{{info.age}}</p>
        <p>{{a}}</p>
        <p>{{b}}</p>
        <p>{{c}}</p>
    </div>
</body>
<script>
    /*
    
        了解一下什么是虚拟DOM和diff算法

        虚拟DOM: 通过对象和数组嵌套组成的形式,记录HTML对应的节点的层级管理 => 虚拟DOM
        diff算法: 对比数据更新前后 两次虚拟DOM结构 => 找出需要更新的html元素 => 触发视图更新


        1. 声明式渲染时
           a. 根据挂载元素的html结构作为默认,生成虚拟DOM
           b. 页面加载时默认渲染一次 => 将对应的虚拟DOM转化为真实DOM

           var vNode1 = {
                tag:"div",  // 标签名
                attrs:{    // 属性
                    id:"#app",
                },
                elm: div#app,  // 对应的真实DOM/文本节点
                text:"",    // 如果是文本节点 => 存文本内容
                children:[  // 子节点
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"hello world" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"100" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"1" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"2" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"3" }]}
                ]
           }

        2. 响应式
           a. 当数据发生改变时, 会根据现有的模板和数据再次生产新的虚拟DOM
           b. 将数据更新前后的虚拟dom进行对比(diff算法), 记录需要更新/修改的节点
           c. 再次更新视图 (此时只有被修改的节点才会更新)

           假如调用了以下方法: 
           vm.reverseMsg();
           vm.addCount();

           var vNode2 = {
                tag:"div",  // 标签名
                attrs:{    // 属性
                    id:"#app",
                },
                elm: div#app,  // 对应的真实DOM/文本节点
                text:"",    // 如果是文本节点 => 存文本内容
                children:[  // 子节点
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"dlrow olleh" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:101 }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"1" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"2" }]}
                    {tag:"p",attrs:{},elm:p, text:"", children:[{ tag:"", attrs:{}, elm:TextNode, text:"3" }]}
                ]
           }

    */
    var vm = new Vue({
        el:"#app", // 挂载的元素(css选择器),当前Vue实例和哪个html元素绑定
        data:{ // 挂载的数据    模型(model)  数据层, 用于存放视图展示所依赖的数据
            msg:"hello world",
            count: 100,
            info:{
                name:"张三",
                age:18,
            },
            a:1,
            b:2,
            c:3
        },
        methods:{ // 挂载的方法  提前定好操作数据的方法,也可以在模板语法中使用
            reverseMsg:function(){
                // this => 当前Vue实例(vue中绝大部分方法都是如此!!)
                console.log(this);

                this.msg = this.msg.split("").reverse().join("");

                // return this.msg.split("").reverse().join(""); //方法返回 反转后的新字符串
            },
            addCount:function(){
                this.count ++; // this.count = this.count + 1;
            }
        },
        
    });


    // 如何调用methods中挂载的方法 => 还是通过Vue实例
    console.log(vm);
    setTimeout(()=>{
        vm.reverseMsg();
        vm.addCount();

        vm.info.name = "李四";
    },5000);



  

</script>
</html>